package com.userdemo.demo.util.base;

import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.rendering.PDFRenderer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.WritableRaster;
import java.io.*;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.util.ArrayList;
import java.util.List;

public class Pdf2Img
{
    private static Logger logger = LoggerFactory.getLogger(Pdf2Img.class);

    public static String getFileMD5(File file) {
	    if (!file.isFile()) {
	        return null;
	    }
	    MessageDigest digest = null;
	    FileInputStream in = null;
	    byte buffer[] = new byte[8192];
	    int len;
	    try {
	        digest =MessageDigest.getInstance("MD5");
	        in = new FileInputStream(file);
	        while ((len = in.read(buffer)) != -1) {
	            digest.update(buffer, 0, len);
	        }
	        BigInteger bigInt = new BigInteger(1, digest.digest());
	        return bigInt.toString(16);
	    } catch (Exception e) {
	        e.printStackTrace();
	        return null;
	    } finally {
	        try {
	            in.close();
	        } catch (Exception e) {
	            e.printStackTrace();
	        }
	    }
	}

	public List doParse( File file, String inDir, String outDir,boolean parseBool) throws IOException
	{

        PDDocument document = null;
        boolean failed = false;

//        LOG.info("Opening: " + file.getName());
        try
        {
            new FileOutputStream(new File(outDir, file.getName() + ".parseerror")).close();
            document = PDDocument.load(file, (String)null);
            String outputPrefix = outDir + '/' + file.getName() + "-";
            int numPages = document.getNumberOfPages();
            List imageList= new ArrayList<String>();
            if(!parseBool){
            	for (int i = 0; i < numPages; i++)
                {
                    String fileName =file.getName()  +"-" +  (i + 1) + ".png";
                    imageList.add(fileName);
                }
            	return imageList;
            }
            if (numPages < 1)
            {
                failed = true;
//                LOG.error("file " + file.getName() + " has < 1 page");
            }
            else
            {
                new File(outDir, file.getName() + ".parseerror").delete();
            }
            
            PDFRenderer renderer = new PDFRenderer(document);
            for (int i = 0; i < numPages; i++)
            {
                String fileName = outputPrefix + (i + 1) + ".png";
                new FileOutputStream(new File(fileName + ".rendererror")).close();
                BufferedImage image = parseImageSize(renderer,i,1);// renderer.renderImageWithDPI(i, 30); // Windows native DPI
                //byte[]   data   =   ((DataBufferByte)image.getData().getDataBuffer()).getData();
                new File(fileName + ".rendererror").delete();
                new FileOutputStream(new File(fileName + ".writeerror")).close();
                ImageIO.write(image, "PNG", new File(fileName));
                new File(fileName + ".writeerror").delete();
                imageList.add( file.getName() +"-"+(i + 1) + ".png");
            }

            //test to see whether file is destroyed in pdfbox
            new FileOutputStream( new File(outDir, file.getName() + ".saveerror")).close();
            File tmpFile = File.createTempFile("pdfbox", ".pdf");
            document.setAllSecurityToBeRemoved(true);
            document.save(tmpFile);
            new File(outDir, file.getName() + ".saveerror").delete();
            new FileOutputStream(new File(outDir, file.getName() + ".reloaderror")).close();
            PDDocument.load(tmpFile, (String)null).close();
            new File(outDir, file.getName() + ".reloaderror").delete();
            tmpFile.delete();
            return imageList;
        }
        catch (IOException e)
        {
            failed = true;
//            logger.error("Error converting file " + file.getName());
            throw e;
        }
        finally
        {
            if (document != null)
            {
                document.close();
            }
        }
	}


	public BufferedImage parseImageSize( PDFRenderer renderer,int i,int definition) throws IOException {
        BufferedImage imageBuff = renderer.renderImageWithDPI(i, 90); // Windows native DPI
        BufferedImage srcImage = resize(imageBuff, 1000, 1200);//产生缩略图
        /*byte[] data = imageBuffToBytes(imageBuff);
        logger.info("image "+i+",data length:"+data.length);
        int step = data.length/1048576;
        if(data.length>1048576){//如果文件大于1M 则需要再压缩
            imageBuff = renderer.renderImageWithDPI(i, 100-9*step);
            //data = imageBuffToBytes(imageBuff);
            logger.info("last image "+i+",data length:"+data.length);
        }*/
        return srcImage;
    }

    private static BufferedImage resize(BufferedImage source, int targetW,int targetH) {
        int type = source.getType();
        BufferedImage target = null;
        double sx = (double) targetW / source.getWidth();
        double sy = (double) targetH / source.getHeight();
        if (sx > sy) {
            sx = sy;
            targetW = (int) (sx * source.getWidth());
        } else {
            sy = sx;
            targetH = (int) (sy * source.getHeight());
        }
        if (type == BufferedImage.TYPE_CUSTOM) {
            ColorModel cm = source.getColorModel();
            WritableRaster raster = cm.createCompatibleWritableRaster(targetW, targetH);
            boolean alphaPremultiplied = cm.isAlphaPremultiplied();
            target = new BufferedImage(cm, raster, alphaPremultiplied, null);
        } else {
            target = new BufferedImage(targetW, targetH, type);
        }
        Graphics2D g = target.createGraphics();
        g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
        g.drawRenderedImage(source, AffineTransform.getScaleInstance(sx, sy));
        g.dispose();
        return target;
    }
    private byte[] imageBuffToBytes(BufferedImage image){
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        try {
            ImageIO.write(image, "png", out);
        } catch (IOException e) {
            e.printStackTrace();
        }
       return  out.toByteArray();
    }
}
